#include "../include/event.h"
#include "../include/object.h"
#include "../include/global_settings.h"
#include "../include/event_info_wrapper.h"
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

vector<EventInfoWrapper> evt_list;
vector<HandlingProc> evt_type;

//external functions

extern "C" void eventInit()
{
	make_heap(evt_list.begin(), evt_list.end());
}

extern "C" void executeEvent(pEventInfo info)
{
	if((unsigned int)info->event_type < evt_type.size())
	{
		evt_type[info->event_type](info);
	}
}

extern "C" void executeTimerEvents()
{
	vector<EventInfoWrapper> temp;
	evt_list.swap(temp);
	while(!temp.empty())
	{
		temp.front().data->time_interval--;
		if(temp.front().data->time_interval == 0)executeEvent(temp.front().data);
		if(temp.front().data->time_interval > 0 &&
			temp.front().priority <= EVT_MAX_PRIORITY)
			evt_list.push_back(temp.front());
		else
			temp.front().destruct();
		pop_heap(temp.begin(), temp.end());
		temp.pop_back();
	}
	make_heap(evt_list.begin(), evt_list.end());
}

extern "C" void addEvent(pEventInfo e, int priority)
{
	EventInfoWrapper new_info(*e, priority);
	evt_list.push_back(new_info);
	push_heap(evt_list.begin(), evt_list.end());
}

extern "C" int findEvent(pEventInfo e_info)
{
	int index = -1;
	for(unsigned int i = 0; i < evt_list.size(); i++)
	{
		if(memcmp(e_info, evt_list[i].data, sizeof(EventInfo)) == 0)
		{
			index = i;
			break;
		}
	}
	return index;
}

extern "C" void removeEvent(pEventInfo e_info)
{
	int index = findEvent(e_info);
	evt_list[index].priority = EVT_MAX_PRIORITY + 1;
	make_heap(evt_list.begin(), evt_list.end());
	evt_list.front().destruct();
	pop_heap(evt_list.begin(), evt_list.end());
	evt_list.pop_back();
}

extern "C" int registerEventType(HandlingProc proc)
{
	evt_type.push_back(proc);
	return evt_type.size() - 1;
}
